/**
 * @Author       : Mo 2427995270@qq.com
 * @Date         : 2022-01-24 13:13:33
 * @LastEditTime : 2025-06-12 15:53:07
 * @FilePath     : \GD32F407_BL\mobl\hal_driver\hal_i2c_master.h
 * @Description  : 软件i2c头文件
 * @Version      : V1.3
 * @History      :
 * @Note         :
 */

#ifndef __hal_i2c_master_H__
#define __hal_i2c_master_H__

/***************************************Includes***********************************/
#include "ll_gpio.h"
#include "os_config.h"
#include <stdint.h>

#if USE_OS == OS_FREERTOS
#include "FreeRTOS.h"
#include "semphr.h"
#endif

/***************************************Macros***********************************/

#define i2c_master_delay_ms(dev, ms) ((dev)->bus_handle->delay_ms(ms))
#define i2c_master_delay_us(dev, us) ((dev)->bus_handle->delay_us(us))

/***************************************Variables***********************************/
typedef enum I2C_ERROR {
    I2C_ERROR_NONE,
    I2C_ERROR_NACK,
    I2C_ERROR_WRITE_NACK,
} i2c_master_error_t;

typedef struct {
    void (*delay_us)(uint32_t us); // 延时函数
    void (*delay_ms)(uint32_t ms); // 延时函数可使用系统延时
    gpio_ll_t gpio_scl;
    gpio_ll_t gpio_sda;
#if USE_OS == OS_FREERTOS
    SemaphoreHandle_t mutex;
#endif
} i2c_master_bus_t;

typedef struct {
    i2c_master_bus_t *bus_handle; // i2c总线
    uint8_t dev_addr;             // 设备地址 7位不包含读写位
    i2c_master_error_t i2c_error_code;   // 错误码
    uint32_t time_series_us;      // 时序 设置为时序要求的最宽容时间 一般2us
    uint32_t time_out_ms;         // 超时时间 无应答超时时间
} i2c_master_dev_t;


/***************************************Functions***********************************/

/**
 * @brief I2C总线初始化
 * @param  bus_handle       总线结构体指针
 * @param  delay_us         延时us
 * @param  delay_ms         延时ms
 * @param  port_scl         scl端口
 * @param  port_sda         sda端口
 * @param  pinnum_scl       scl管脚
 * @param  pinnum_sda       sda管脚
 * @param  pullup           1上拉 0无上拉
 * @return int 0成功 -1失败
 * @note null
 */
int i2c_master_bus_init(
    i2c_master_bus_t *bus_handle,
    void (*delay_us)(uint32_t us),
    void (*delay_ms)(uint32_t ms),
    uint32_t port_scl, uint32_t port_sda, 
    uint32_t pinnum_scl, uint32_t pinnum_sda,
    int pullup);
/**
 * @brief I2C总线添加设备
 * @param  bus_handle       总线结构体指针
 * @param  dev_handle       设备结构体指针
 * @param  dev_addr         设备地址 7位不包含读写位
 * @param  time_series_us   时序最低要求时间
 * @param  time_out_ms      应答超时时间
 * @return int 0成功 -1失败
 * @note null
 */
int i2c_master_bus_add_dev(
    i2c_master_bus_t *bus_handle,
    i2c_master_dev_t *dev_handle,
    uint8_t dev_addr,
    uint32_t time_series_us,
    uint32_t time_out_ms);
/**
 * @brief I2C读取多个字节
 * @param  dev_handle
 * @param  buf              读取的数据存在这
 * @param  buf_len          读取数据的数量 byte
 * @return int 0成功 -1失败
 * @note null
 */
int i2c_master_read(i2c_master_dev_t *dev_handle, void *buf, int32_t buf_len);
/**
 * @brief I2C写入多个字节
 * @param  dev_handle
 * @param  buf              要写入的数据
 * @param  buf_len          写入数据的数量 byte
 * @return int 0成功 -1失败
 * @note null
 */
int i2c_master_write(i2c_master_dev_t *dev_handle, const void *buf, int32_t buf_len);
/**
 * @brief I2C先写后读
 * @param  dev_handle
 * @param  write_buf        要写入的数据
 * @param  write_buf_len    数据量
 * @param  read_buf         要读取的数据
 * @param  read_buf_len     数据量
 * @return int 0成功 -1失败
 * @note null
 */
int i2c_master_write_and_read(i2c_master_dev_t *dev_handle, const void *write_buf, int32_t write_buf_len, void *read_buf, int32_t read_buf_len);
/**
 * @brief I2C连写(只有一次起始和停止信号)
 * @param  dev_handle
 * @param  buffer           存多组数据数组的指针，数组的每个元素是一个指向数据的指针
 * @param  buffer_len       存多组数据长度的数组的指针，数组的每个元素是数据的长度
 * @param  buffer_num       存多组数据的数组的长度
 * @return int 0成功 -1失败
 * @note null
 */
int i2c_master_multi_write(i2c_master_dev_t *dev_handle, const void *(*buffer)[], int32_t (*buffer_len)[], int32_t buffer_num);
/**
 * @brief 等待SCL被器件释放
 * @param  dev_handle
 * @param  ms                 超时时间 ms
 * @return int -1超时没有释放 0释放
 * @note null
 */
int i2c_master_wait_scl_freed(i2c_master_dev_t *dev_handle, uint32_t ms);

/***************************************statement***********************************/


#endif
/* [] END OF FILE */
